﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
using ProtocoloPropietario;
using System.Threading;

namespace Cliente
{
    class Conexion
    {
        private Socket _socCliente;
        private Socket _socServidor;
        private IPAddress _ipMultiCastServidor;
        private IPAddress _ipCliente;
        private int _numPuertoCliente;
        private int _numPuertoMCServ;

        public Socket SocServidor
        {
            get { return _socServidor; }
            set { _socServidor = value; }
        }

        public Socket SocCliente
        {
            get { return _socCliente; }
            set { _socCliente = value; }
        }

        public Conexion(IPAddress ipMulti, IPAddress ipclien, int puertoMCSe, int puertocliente)
        {
            _ipMultiCastServidor = ipMulti;
            _ipCliente = ipclien;
            _numPuertoMCServ = puertoMCSe;
            _numPuertoCliente = puertocliente;
            _socCliente = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            _socServidor = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        }

        public Servidor BuscarServidor()
        {
            try
            {
                bool obtuvoBandaAncha = false;
                List<string> listRes = new List<string>();
                while (!obtuvoBandaAncha)
                {
                    Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
                    socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, new MulticastOption(_ipMultiCastServidor));
                    socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastTimeToLive, 2);
                    _socCliente = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                    _socServidor = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

                    IPEndPoint ipep = new IPEndPoint(_ipMultiCastServidor, _numPuertoMCServ);
                    Console.WriteLine("Connecting...");
                    socket.Connect(ipep);

                    string strMsj = _ipCliente.ToString() + Protocolo.SEPARADOR + _numPuertoCliente;
                    MensajeProtocolo msj = new MensajeProtocolo(Protocolo.Header.REQ, Protocolo.Comando.CLIENTE_CONEXION, strMsj.Length, strMsj);
                    byte[] b = msj.ConvertirAByte();
                    socket.Send(b, b.Length, SocketFlags.None);
                    socket.Close();

                    AceptarTCP();
                    byte[] paquete = new byte[30];
                    _socCliente.Receive(paquete);
                    MensajeProtocolo msg = MensajeProtocolo.ObtenerMensajeProtocolo(paquete);
                    listRes = msg.InfoDatos();
                    _socCliente.Close();
                    _socServidor.Close();

                    if (msj.Cmd == Protocolo.Comando.DORMIR)
                    {
                        Thread.Sleep(1000);
                    }
                    else
                    {
                        obtuvoBandaAncha = true;
                    }
                }
                Servidor serv = new Servidor(IPAddress.Parse(listRes[0]), Int32.Parse(listRes[1]), Int32.Parse(listRes[2]));
                return serv;

            }
            catch (SocketException e)
            {
                _socCliente.Close();
                _socServidor.Close();
                return BuscarServidor();
            }
            catch (Exception e)
            {
                _socCliente.Close();
                _socServidor.Close();
                return BuscarServidor();
            }
        }


        private void AceptarTCP()
        {
            IPEndPoint ipEndAEscuchar = new IPEndPoint(_ipCliente, _numPuertoCliente);
            _socServidor.Bind(ipEndAEscuchar);
            _socServidor.Listen(5);
            _socCliente = _socServidor.Accept();
        }
    }
}
